package com.example.selenium.queue.rabbitmq;

import com.example.selenium.common.Result;
import com.example.selenium.queue.rabbitmq.config.RabbitMqConstants;
import com.example.selenium.queue.rabbitmq.f.MessageInfo;
import com.example.selenium.service.RabbitMqListenerService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 *  消息监听器
 * @author  liu
 */
@Slf4j
@Component("rabbitMqListener")
public class RabbitMqListener {

    @Autowired
    private RabbitMqListenerService rabbitMqListenerService;


    /**
     * 监听运单号列表,根据运单号去查询运单详情
     * channel.basicAsk的参数意义如下
     * basicAck：表示成功确认，使用此回执方法后，消息会被rabbitmq broker 删除
     * deliveryTag：表示消息投递序号，每次消费消息或者消息重新投递后，deliveryTag都会增加。手动消息确认模式下，我们可以对指定deliveryTag的消息进行ack、nack、reject等操作
     * multiple：是否批量确认，值为 true 则会一次性 ack所有小于当前消息 deliveryTag 的消息
     * @param msg 自定义消息类型，这里可以根据发送消息时，传递的参数类型是什么，我们也可以自定义这个类型即可，底层会被字段映射到该类型上
     * @param channel
     * @param message
     * @throws IOException
     */
    @RabbitHandler
    @RabbitListener(queues = RabbitMqConstants.QUEUE_WAYBILL_LIST)
    public void processHandler(MessageInfo msg, Channel channel, Message message) throws IOException {
        try {
            log.info(RabbitMqConstants.QUEUE_WAYBILL_LIST+"队列收到消息：{}", msg);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }  catch (Exception e) {
            if (message.getMessageProperties().getRedelivered()) {
                log.error("消息已重复处理失败,拒绝再次接收...");
                // 拒绝消息
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            } else {
                log.error("消息即将再次返回队列处理...");
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            }
        }
    }

    /**
     * 运单详情
     * @param msg
     * @param channel
     * @param message
     * @throws IOException
     */
    @RabbitHandler
    @RabbitListener(queues = RabbitMqConstants.QUEUE_WAYBILL_DETAIL)
    public void handleWaybillDetail(MessageInfo msg, Channel channel, Message message) throws IOException {
        try {
            Result result = rabbitMqListenerService.handleWaybillDetail(msg);
            if(result.getCode()==200){
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            }
        }  catch (Exception e) {
            if (message.getMessageProperties().getRedelivered()) {
                log.error("消息已重复处理失败,拒绝再次接收...");
                // 拒绝消息
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            } else {
                log.error("消息即将再次返回队列处理...");
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            }
        }
    }

    /**
     * 支付详情
     * @param msg 自定义消息类型，这里可以根据发送消息时，传递的参数类型是什么，我们也可以自定义这个类型即可，底层会被字段映射到该类型上
     * @param channel
     * @param message
     * @throws IOException
     */
    @RabbitHandler
    @RabbitListener(queues = RabbitMqConstants.QUEUE_PAYINFO_DETAIL)
    public void handlePayInfoDetail(MessageInfo msg, Channel channel, Message message) throws IOException {
        try {
            Result result = rabbitMqListenerService.handlePayInfoDetail(msg);
            if(result.getCode()==200){
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            }
        }  catch (Exception e) {
            if (message.getMessageProperties().getRedelivered()) {
                log.error("消息已重复处理失败,拒绝再次接收...");
                // 拒绝消息
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            } else {
                log.error("消息即将再次返回队列处理...");
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            }
        }
    }
}
